///////////////////////////////////////////////////////////////////////////////
//
// lighthouse3D - 3D Software Library
//
// File: C3DLibInterface.cpp
//
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2003-2013 Marcus Reinhardt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
///////////////////////////////////////////////////////////////////////////////
//
// You can find a copy of the GNU General Public License (gpl.txt) in the
// directory of the library.
//
///////////////////////////////////////////////////////////////////////////////
#include "C3DLibrary.h"
#include "C3DLibInterface.h"

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::C3DLibInterface( ... )
///////////////////////////////////////////////////////////////////////////////
C3DLibInterface::C3DLibInterface()
{
  pLibRef = NULL;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::checkBinding( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::checkBinding()
{
  if (pLibRef == NULL)
    return false;

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::~C3DLibInterface( ... )
///////////////////////////////////////////////////////////////////////////////
C3DLibInterface::~C3DLibInterface()
{
  release();
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::release( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::release()
{
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::bindLibrary( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::bindLibrary(C3DLibrary *pLocalLibRef)
{
  pLibRef = pLocalLibRef;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setupUseInternalScreen( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setupUseInternalScreen()
{
  if (!checkBinding())
    return;

  pLibRef->setupUseInternalScreen();
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setupColDetection( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setupColDetection(int ColDetection)
{
  if (!checkBinding())
    return;

  pLibRef->setupColDetection(ColDetection);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setupBFCulling( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setupBFCulling(int bfCulling)
{
  if (!checkBinding())
    return;

  pLibRef->setupBFCulling(bfCulling);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setupTexFilter( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setupFSAAFilter(int filter)
{
  if (!checkBinding())
    return;

  pLibRef->setupFSAAFilter(filter);
}
///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setupTexFilter( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setupTexFilter(int filter)
{
  if (!checkBinding())
    return;

  pLibRef->libSetup.texFilter = filter;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setupLighting( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setupLighting(int lighting)
{
  if (!checkBinding())
    return;

  pLibRef->setupLighting(lighting);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setupRenderer( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setupRenderer(int renderer)
{
  if (!checkBinding())
    return;

  pLibRef->setupRenderer(renderer);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setupShader( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setupShader(int shader)
{
  if (!checkBinding())
    return;

  pLibRef->setupShader(shader);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::FogSynthesis( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setupFogSynthesis(int fog)
{
  if (!checkBinding())
    return;

  pLibRef->setupFogSynthesis(fog);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setupIncShader( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setupIncShader()
{
  if (!checkBinding())
    return;

  pLibRef->setupIncShader();
}

void C3DLibInterface::setupLogo(int logo)
{
  if (!checkBinding())
    return;

	pLibRef->setupLogo(logo);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::getPixel( ... )
///////////////////////////////////////////////////////////////////////////////
unsigned int C3DLibInterface::getPixel(int x, int y)
{
  if (!checkBinding())
    return 0;

  return pLibRef->getPixel(x, y);

}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::getPixelRelative( ... )
///////////////////////////////////////////////////////////////////////////////
unsigned int C3DLibInterface::getPixelRelative(int x, int y, int relX, int relY)
{
  if (!checkBinding())
    return 0;

  return pLibRef->getPixelRelative(x, y, relX, relY);

}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::getScreenHandle( ... )
///////////////////////////////////////////////////////////////////////////////
C2DScreen *C3DLibInterface::getScreenHandle()
{
  if (!checkBinding())
    return 0;

  return &pLibRef->screen2D;

}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::clear( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::clear()
{
#ifdef __MULTI_CORE_SUPPORT
  unsigned char i;
#endif

  if (!checkBinding())
    return;

  pLibRef->screen2D.clear();
      
  pLibRef->zBuffer.clear();  

#ifdef __MULTI_CORE_SUPPORT
  for (i=0; i<__CPU_CORES_SUPPORTED; i++) {
    pLibRef->screen2DCPU[i]->clear();
    pLibRef->zBufferCPU[i]->clear();
  }
#endif
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::resizeScreen( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::resizeScreen(int sX, int sY)
{
#ifdef __MULTI_CORE_SUPPORT
  unsigned char i;
#endif

  if (!checkBinding())
    return;

  pLibRef->screenSizeX = sX;
  pLibRef->screenSizeY = sY;
  pLibRef->screenCenterX = (int)(float(sX) / 2);
  pLibRef->screenCenterY = (int)(float(sY) / 2);
  pLibRef->opticalCorrectness = (int)(float(sX) / 2);

  pLibRef->screen2D.setSize(sX, sY);
  pLibRef->zBuffer.setSize(sX, sY);

#ifdef __MULTI_CORE_SUPPORT
  for (i=0; i<__CPU_CORES_SUPPORTED; i++) {
    pLibRef->screen2DCPU[i]->setSize(sX, sY);
    pLibRef->zBufferCPU[i]->setSize(sX, sY);
  }
#endif
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::update3DScene( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::update3DScene()
{
  if (!checkBinding())
    return false;

  return pLibRef->renderScene();
}


///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::createNewObject( ... )
///////////////////////////////////////////////////////////////////////////////
// creates a new empty object
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::createNewObject()
{
  if (!checkBinding())
    return false;

  pLibRef->addNewMesh();
  pLibRef->m_meshStorage.getMesh(pLibRef->getMeshCount()-1)->clear();

  pLibRef->initPositionMap(pLibRef->getMeshCount()-1);

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::finalizeNewObject( ... )
///////////////////////////////////////////////////////////////////////////////
// finalizes the new object
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::finalizeNewObject()
{
  if (!checkBinding())
    return false;

  pLibRef->geometricPreparation(pLibRef->getMeshCount()-1);

  if ( pLibRef->calcPlaneNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  if ( pLibRef->calcVertexNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::finalizeObject( ... )
///////////////////////////////////////////////////////////////////////////////
// finalizes a specified object
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::finalizeObject(int mesh)
{
  if (!checkBinding())
    return false;

  pLibRef->geometricPreparation(mesh);

  if ( pLibRef->calcPlaneNormals(mesh) == false )
      return false;

  if ( pLibRef->calcVertexNormals(mesh) == false )
      return false;

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::createPlane( ... )
///////////////////////////////////////////////////////////////////////////////
// creates a plane
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::createPlane(const char *texname)
{
  if (!checkBinding())
    return false;

  pLibRef->addNewMesh();
  pLibRef->m_meshStorage.getMesh(pLibRef->getMeshCount()-1)->clear();

  pLibRef->initPositionMap(pLibRef->getMeshCount()-1);

  if (pLibRef->objectCreator.createPlane(&pLibRef->m_meshStorage, texname) == false) {
      return false;
  }

  pLibRef->geometricPreparation(pLibRef->getMeshCount()-1);

  if ( pLibRef->calcPlaneNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  if ( pLibRef->calcVertexNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::createPyramid( ... )
///////////////////////////////////////////////////////////////////////////////
// creates a pyramid
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::createPyramid(const char *texname)
{
  if (!checkBinding())
    return false;

  pLibRef->addNewMesh();
  pLibRef->m_meshStorage.getMesh(pLibRef->getMeshCount()-1)->clear();

  pLibRef->initPositionMap(pLibRef->getMeshCount()-1);

  if (pLibRef->objectCreator.createPyramid(&pLibRef->m_meshStorage, texname) == false) {
      return false;
  }

  pLibRef->geometricPreparation(pLibRef->getMeshCount()-1);

  if ( pLibRef->calcPlaneNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  if ( pLibRef->calcVertexNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::createCube( ... )
///////////////////////////////////////////////////////////////////////////////
// creates a cube
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::createCube(const char *texname)
{
  if (!checkBinding())
    return false;

  pLibRef->addNewMesh();
  pLibRef->m_meshStorage.getMesh(pLibRef->getMeshCount()-1)->clear();

  pLibRef->initPositionMap(pLibRef->getMeshCount()-1);

  if (pLibRef->objectCreator.createCube(&pLibRef->m_meshStorage, texname) == false) {
      return false;
  }

  pLibRef->geometricPreparation(pLibRef->getMeshCount()-1);

  if ( pLibRef->calcPlaneNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  if ( pLibRef->calcVertexNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::createCylinder( ... )
///////////////////////////////////////////////////////////////////////////////
// creates a cylinder
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::createCylinder(const char *texname)
{
  if (!checkBinding())
    return false;

  pLibRef->addNewMesh();
  pLibRef->m_meshStorage.getMesh(pLibRef->getMeshCount()-1)->clear();

  pLibRef->initPositionMap(pLibRef->getMeshCount()-1);

  if (pLibRef->objectCreator.createCylinder(&pLibRef->m_meshStorage, texname) == false) {
      return false;
  }

  pLibRef->geometricPreparation(pLibRef->getMeshCount()-1);

  if ( pLibRef->calcPlaneNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  if ( pLibRef->calcVertexNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::createCone( ... )
///////////////////////////////////////////////////////////////////////////////
// creates a cone
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::createCone(const char *texname)
{
  if (!checkBinding())
    return false;

  pLibRef->addNewMesh();
  pLibRef->m_meshStorage.getMesh(pLibRef->getMeshCount()-1)->clear();

  pLibRef->initPositionMap(pLibRef->getMeshCount()-1);

  if (pLibRef->objectCreator.createCone(&pLibRef->m_meshStorage, texname) == false) {
      return false;
  }

  pLibRef->geometricPreparation(pLibRef->getMeshCount()-1);

  if ( pLibRef->calcPlaneNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  if ( pLibRef->calcVertexNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::createSphere( ... )
///////////////////////////////////////////////////////////////////////////////
// creates a sphere
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::createSphere(const char *texname)
{
  if (!checkBinding())
    return false;

  pLibRef->addNewMesh();
  pLibRef->m_meshStorage.getMesh(pLibRef->getMeshCount()-1)->clear();

  pLibRef->initPositionMap(pLibRef->getMeshCount()-1);

  if (pLibRef->objectCreator.createSphere(&pLibRef->m_meshStorage, texname) == false) {
      return false;
  }

  pLibRef->geometricPreparation(pLibRef->getMeshCount()-1);

  if ( pLibRef->calcPlaneNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  if ( pLibRef->calcVertexNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::createSimpleSurface( ... )
///////////////////////////////////////////////////////////////////////////////
// creates a simple surface
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::createSimpleSurface(const char *texname, const char *texname2,
                                     const char *texname3, const char *texname4, const char *texname5)
{
  if (!checkBinding())
    return false;

  pLibRef->addNewMesh();
  pLibRef->m_meshStorage.getMesh(pLibRef->getMeshCount()-1)->clear();

  if (pLibRef->objectCreator.createSimpleSurface(&pLibRef->m_meshStorage, texname, texname2,
                                                   texname3, texname4, texname5) == false) {                                        
    return false;
  }

  pLibRef->initPositionMap(pLibRef->getMeshCount()-1);

  pLibRef->geometricPreparation(pLibRef->getMeshCount()-1);

  if ( pLibRef->calcPlaneNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  if ( pLibRef->calcVertexNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::createHeightMapSurface( ... )
///////////////////////////////////////////////////////////////////////////////
// creates a surface from a heightmap and a texture
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::createHeightMapSurface(const char *texname, const char *texname2)
{
  if (!checkBinding())
    return false;

  pLibRef->addNewMesh();
  pLibRef->m_meshStorage.getMesh(pLibRef->getMeshCount()-1)->clear();

  pLibRef->initPositionMap(pLibRef->getMeshCount()-1);

  if (pLibRef->objectCreator.createHeightMapSurface(&pLibRef->m_meshStorage, texname, texname2) == false)
										   return false;

  pLibRef->initPositionMap(pLibRef->getMeshCount()-1);
  pLibRef->geometricPreparation(pLibRef->getMeshCount()-1);

  if ( pLibRef->calcPlaneNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  if ( pLibRef->calcVertexNormals(pLibRef->getMeshCount()-1) == false )
      return false;

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setPlaneParams( ... )
///////////////////////////////////////////////////////////////////////////////
// sets the parameter for creating a plane
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setPlaneParams(float s, int ps)
{
  if (!checkBinding())
    return;

  pLibRef->objectCreator.planeSize = s;
  pLibRef->objectCreator.planeSelect = ps;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setPyramidParams( ... )
///////////////////////////////////////////////////////////////////////////////
// sets the parameter for creating a pyramid
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setPyramidParams(float s)
{
  if (!checkBinding())
    return;

  pLibRef->objectCreator.pyramidSize = s;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setCubeParams( ... )
///////////////////////////////////////////////////////////////////////////////
// sets the parameter for creating a cube
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setCubeParams(float s, bool tl, bool bl)
{
  if (!checkBinding())
    return;

  pLibRef->objectCreator.cubeSize = s;
  pLibRef->objectCreator.cubeTopLess = tl;
  pLibRef->objectCreator.cubeBottomLess = bl;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setCylinderParams( ... )
///////////////////////////////////////////////////////////////////////////////
// sets the parameter for creating a cylinder
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setCylinderParams(float h, float rt, float rc, int c)
{
  if (!checkBinding())
    return;

  pLibRef->objectCreator.cylinderHeight = h;
  pLibRef->objectCreator.cylinderRadiusTop = rt;
  pLibRef->objectCreator.cylinderRadiusBottom = rc;
  pLibRef->objectCreator.cylinderCirclePoints = c;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setConeParams( ... )
///////////////////////////////////////////////////////////////////////////////
// sets the parameter for creating a cone
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setConeParams(float h, float r, int c)
{
  if (!checkBinding())
    return;

  pLibRef->objectCreator.coneHeight = h;
  pLibRef->objectCreator.coneRadiusBottom = r;
  pLibRef->objectCreator.coneCirclePoints = c;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setSphereParams( ... )
///////////////////////////////////////////////////////////////////////////////
// sets the parameter for creating a sphere
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setSphereParams(float c, float p, float r)
{
  if (!checkBinding())
    return;

  pLibRef->objectCreator.sphereVCircles = c;
  pLibRef->objectCreator.sphereRadius = r;
  pLibRef->objectCreator.spherePoints = p;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setHeightMapParams( ... )
///////////////////////////////////////////////////////////////////////////////
// sets the parameter for creating a height map
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setHeightMapParams(float mX, float mY, int autoBal)
{
  if (!checkBinding())
    return;

  pLibRef->objectCreator.heightMapSurfaceMultiplikator = mX;
  pLibRef->objectCreator.heightMapSurfaceMultiplikatorY = mY;
  pLibRef->objectCreator.heightMapSurfaceAutoBalance = autoBal;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::load3DSFile( ... )
///////////////////////////////////////////////////////////////////////////////
// loads the 3DS File specified by fname
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::load3DSFile(const char *fname)
{
  bool ok;
  int mc, i;
    
  if (!checkBinding())
    return false;

  mc = pLibRef->getMeshCount();  

  ok = pLibRef->fileHandler.load3DSToMeshStorage(fname, &pLibRef->m_meshStorage);
  
  // Nothing changed!
  if ( mc == pLibRef->getMeshCount() )
       return ok;

  for (i = mc; i < pLibRef->getMeshCount(); i++) {

	   pLibRef->initPositionMap(i);
       pLibRef->geometricPreparation(i);

       if ( pLibRef->calcPlaneNormals(i) == false )
           return false;

       if ( pLibRef->calcVertexNormals(i) == false )
           return false;
  }

  return ok;

}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::loadOBJFile( ... )
///////////////////////////////////////////////////////////////////////////////
// loads the OBJ File specified by fname
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::loadOBJFile(const char *fname)
{
  bool ok;
  int mc, i;
    
  if (!checkBinding())
    return false;

  mc = pLibRef->getMeshCount();  

  ok = pLibRef->fileHandler.loadOBJToMeshStorage(fname, &pLibRef->m_meshStorage);

  // Nothing changed!
  if ( mc == pLibRef->getMeshCount() )
       return ok;

  for (i = mc; i < pLibRef->getMeshCount(); i++) {

	   pLibRef->initPositionMap(i);
       pLibRef->geometricPreparation(i);

       if ( pLibRef->calcPlaneNormals(i) == false )
           return false;

       if ( pLibRef->calcVertexNormals(i) == false )
		   return false;

  }

  return ok;

}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::getFileExtension( ... )
///////////////////////////////////////////////////////////////////////////////
// extracts the file's extension
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::getFileExtension(char *fname, char *ext)
{
  if (!checkBinding())
    return false;

  pLibRef->fileHandler.getExtensionFromFilename(fname, ext);

  return true;
}
///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setAmbientLight( ... )
///////////////////////////////////////////////////////////////////////////////
// Set the ambient light for the scene
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::setAmbientLight(float i)
{
  TLightSource l;
  
  if (!checkBinding())
    return false;

  l.ia = i;
  
  pLibRef->lightingHandler.setAmbientLight(l);
  
  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::addDotLight( ... )
///////////////////////////////////////////////////////////////////////////////
// Add a dot light to the scene
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::addDotLight(float x, float y, float z, int r, int g, int b, float id, float is)
{
  TLightSource l;
  
  if (!checkBinding())
    return false;

  l.x = x;
  l.y = y;
  l.z = z;
  l.r = r;
  l.g = g;
  l.b = b;
  l.id = id;
  l.is = is;
  
  pLibRef->lightingHandler.addDotLight(l);

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::addCamera( ... )
///////////////////////////////////////////////////////////////////////////////
// Add a camera to the scene
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::addCamera(int rx, int ry, int rz, float tx, float ty, float tz, float cn, float cf)
{
  TCamera vp;
  
  if (!checkBinding())
    return false;

  vp.trX = -tx;
  vp.trY = -ty;
  vp.trZ = -tz;
  
  vp.viewVec.d[0] = 0;
  vp.viewVec.d[1] = 0;
  vp.viewVec.d[2] = 1;
  
  vp.downVec.d[0] = 0;
  vp.downVec.d[1] = 1;
  vp.downVec.d[2] = 0;

  vp.rightVec.d[0] = 1;
  vp.rightVec.d[1] = 0;
  vp.rightVec.d[2] = 0;
  
  vp.nearClipping = cn;
  vp.farClipping = cf;
  
  pLibRef->cameraHandler.addCamera(vp);
  
  pLibRef->cameraHandler.turnDownCamera(pLibRef->cameraHandler.getCameraCount()-1,rx);
  pLibRef->cameraHandler.turnRightCamera(pLibRef->cameraHandler.getCameraCount()-1,ry);

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setActiveCamera( ... )
///////////////////////////////////////////////////////////////////////////////
// Set active camera
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::setActiveCamera(int i)
{
  if (!checkBinding())
    return false;

  if ( (i < 0) || (i >= pLibRef->cameraHandler.getCameraCount()) )
    return false;
      
  pLibRef->cameraHandler.setActiveCamera(i);    
      
  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::resetActiveCamera( ... )
///////////////////////////////////////////////////////////////////////////////
// Reset active camera
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::resetActiveCamera() {
  if (!checkBinding())
    return;

  pLibRef->cameraHandler.resetActiveCamera() ;    
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setNextCamera( ... )
///////////////////////////////////////////////////////////////////////////////
// Sets the follow up Camera as the active one
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::setNextCamera()
{
  if (!checkBinding())
    return false;

  pLibRef->cameraHandler.setNextCamera();    
      
  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::getActiveCameraInformation( ... )
///////////////////////////////////////////////////////////////////////////////
// Gets all information about the active camera
///////////////////////////////////////////////////////////////////////////////
TCamera C3DLibInterface::getActiveCameraInformation()
{
  // Issue: Needs IF redesign
#if 0
  if (!checkBinding())
    return NULL;
#endif

  return pLibRef->cameraHandler.getCameraInformation(-1);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setSpecularPower( ... )
///////////////////////////////////////////////////////////////////////////////
// Sets the dispersion of the specular light
// The higher the value the lesser the dispersion
// Therefore metallic materials have a low value (1-10) and
// papers or wood have a very high value (30++)!
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::setSpecularPower(int i)
{
  if (!checkBinding())
    return false;

  if (i < 1) return false;
  
  pLibRef->lightingHandler.setSpecularPower(i);
  
  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::moveAheadCamera( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::moveAheadCamera(float speed)
{
  if (!checkBinding())
    return false;

  pLibRef->cameraHandler.moveAheadCamera(-1, speed);

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::moveBackCamera( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::moveBackCamera(float speed)
{
  if (!checkBinding())
    return false;

  pLibRef->cameraHandler.moveBackCamera(-1, speed);

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::moveLeftCamera( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::moveLeftCamera(float speed)
{
  if (!checkBinding())
    return false;

  pLibRef->cameraHandler.moveLeftCamera(-1, speed);

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::moveRightCamera( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::moveRightCamera(float speed)
{
  if (!checkBinding())
    return false;

  pLibRef->cameraHandler.moveRightCamera(-1, speed);

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::moveUpCamera( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::moveUpCamera(float speed)
{
  if (!checkBinding())
    return false;

  pLibRef->cameraHandler.moveUpCamera(-1, speed);

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::moveDownCamera( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::moveDownCamera(float speed)
{
  if (!checkBinding())
    return false;

  pLibRef->cameraHandler.moveDownCamera(-1, speed);

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::turnUpCamera( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::turnUpCamera(int speed)
{
  if (!checkBinding())
    return false;

  pLibRef->cameraHandler.turnUpCamera(-1, speed);

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::turnDownCamera( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::turnDownCamera(int speed)
{
  if (!checkBinding())
    return false;

  pLibRef->cameraHandler.turnDownCamera(-1, speed);

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::turnLeftCamera( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::turnLeftCamera(int speed)
{
  if (!checkBinding())
    return false;

  pLibRef->cameraHandler.turnLeftCamera(-1, speed);

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::turnRightCamera( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::turnRightCamera(int speed)
{
  if (!checkBinding())
    return false;

  pLibRef->cameraHandler.turnRightCamera(-1, speed);

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setColDistance ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::setColDistance(float d)
{
  if (!checkBinding())
    return false;

  pLibRef->cameraHandler.setColDistance(-1, d);

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::getTriangleCount( ... )
///////////////////////////////////////////////////////////////////////////////
int C3DLibInterface::getTrianglesCount()
{
  int i;
  int count = 0;

  if (!checkBinding())
    return 0;

  for (i = 0; i < pLibRef->getMeshCount(); i++)
  {
       count += pLibRef->getMesh(i)->getFaceCount();
  }  
  
  return count;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::getVertexCount( ... )
///////////////////////////////////////////////////////////////////////////////
int C3DLibInterface::getVertexCount()
{
  int i;
  int count = 0;

  if (!checkBinding())
    return 0;

  for (i = 0; i < pLibRef->getMeshCount(); i++)
  {
	   count += pLibRef->getMesh(i)->getVertCount();
  }

  return count;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::getRenderedTrianglesCount( ... )
///////////////////////////////////////////////////////////////////////////////
int C3DLibInterface::getRenderedTrianglesCount()
{
  if (!checkBinding())
    return 0;

  return pLibRef->renderedTrianglesCount;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::getRenderedPixelsCount( ... )
///////////////////////////////////////////////////////////////////////////////
int C3DLibInterface::getRenderedPixelsCount()
{
  if (!checkBinding())
    return 0;

  return pLibRef->renderedPixelsCount;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::getRenderedHLinesCount( ... )
///////////////////////////////////////////////////////////////////////////////
int C3DLibInterface::getRenderedHLinesCount()
{
  if (!checkBinding())
    return 0;

  return pLibRef->renderedHLinesCount;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setFogSynthesis( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setFogSynthesis(float nd, float fd, float fdn, int r, int g, int b)
{
#ifdef __MULTI_CORE_SUPPORT                                     
  int i;
#endif

  if (!checkBinding())
    return;

  pLibRef->fogSynthesis.setFogParameters(nd, fd, fdn, r, g, b);
#ifdef __MULTI_CORE_SUPPORT                                     
  for (i=0; i<__CPU_CORES_SUPPORTED; i++)
    pLibRef->fogSynthesisCPU[i]->setFogParameters(nd, fd, fdn, r, g, b);
#endif
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::getDotLight( ... )
///////////////////////////////////////////////////////////////////////////////
TLightSource *C3DLibInterface::getDotLight(int i)
{
  if (!checkBinding())
    return NULL;

  return pLibRef->lightingHandler.getDotLight(i);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setDotLight( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::setDotLight(int i, TLightSource &l)
{
  if (!checkBinding())
    return false;

  pLibRef->lightingHandler.setDotLight(i, l);
  
  return true;
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setBackgroundPicture( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::setBackgroundPicture(char *f)
{
  if (!checkBinding())
    return false;

  return pLibRef->screen2D.setBackgroundPicture(f);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::saveSnapshot( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::saveSnapshot(char *f)
{
  if (!checkBinding())
    return false;

  return pLibRef->screen2D.saveBufferAsTGA(f);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::loadFont( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::loadFont(char *f)
{
  if (!checkBinding())
    return false;

  return pLibRef->screen2D.loadFont(f);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::drawText( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::drawText(int x, int y, char *t)
{
  if (!checkBinding())
    return false;

  return pLibRef->screen2D.drawText(x, y, t);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::drawBox( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::drawBox(int x1, int y1, int x2, int y2, int y3, unsigned int c1, unsigned int c2, unsigned int c3)
{
  if (!checkBinding())
    return;

  return pLibRef->screen2D.drawBox(x1, y1, x2, y2, y3, c1, c2, c3);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setFontColor( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setFontColor(unsigned int c)
{
  if (!checkBinding())
    return;

  pLibRef->screen2D.setFontColor(c);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::drawGUIBox( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::drawGUIBox(int x1, int y1, int x2, int y2, int y3, unsigned int c1, unsigned int c2, unsigned int c3, char *t)
{
  if (!checkBinding())
    return;

  pLibRef->screen2D.drawGUIBox(x1, y1, x2, y2, y3, c1, c2, c3, t);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::drawGUIStdBox( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::drawGUIStdBox(int x1, int y1, int x2, int y2, int y3, char *t)
{
  if (!checkBinding())
    return;

  pLibRef->screen2D.drawGUIStdBox(x1, y1, x2, y2, y3, t);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setGUITransparency( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setGUITransparency(float t)
{
  if (!checkBinding())
    return;

  pLibRef->screen2D.setGUITransparency(t);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setCaption( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setCaption(TGUIHandle *h, char *c)
{
  if (!checkBinding())
    return;

  pLibRef->screen2D.setCaption(h,c);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::setVisible( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::setVisible(TGUIHandle *h, bool v)
{
  if (!checkBinding())
    return;

  pLibRef->screen2D.setVisible(h,v);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::updateGUIElements( ... )
///////////////////////////////////////////////////////////////////////////////
void C3DLibInterface::updateGUIElements() 
{ 
  if (!checkBinding())
    return;

   pLibRef->screen2D.repaintGUIElements(); 
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::isOverGUIElement( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::isOverGUIElement(TGUIHandle *h, int x, int y) 
{
  if (!checkBinding())
    return false;

  return pLibRef->screen2D.isOverGUIElement(h, x, y);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::isOverNoGUIElement( ... )
///////////////////////////////////////////////////////////////////////////////
bool C3DLibInterface::isOverNoGUIElement(int x, int y) 
{
  if (!checkBinding())
    return false;

  return pLibRef->screen2D.isOverNoGUIElement(x, y);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::getMainHandle( ... )
///////////////////////////////////////////////////////////////////////////////
TGUIHandle *C3DLibInterface::getMainHandle()
{ 
  if (!checkBinding())
    return NULL;

  return pLibRef->screen2D.getMainHandle();
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::createButton( ... )
///////////////////////////////////////////////////////////////////////////////
TGUIHandle *C3DLibInterface::createButton(TGUIHandle *handle, int x, int y, int w, int h, char *t)
{
  if (!checkBinding())
    return NULL;

  return pLibRef->screen2D.createButton(handle, x, y, w, h, t);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::createWindow( ... )
///////////////////////////////////////////////////////////////////////////////
TGUIHandle *C3DLibInterface::createWindow(TGUIHandle *handle, int x, int y, int w, int h, int h2, char *t)
{
  if (!checkBinding())
    return NULL;

  return pLibRef->screen2D.createWindow(handle, x, y, w, h, h2, t);
}

///////////////////////////////////////////////////////////////////////////////
// C3DLibInterface::createLabel( ... )
///////////////////////////////////////////////////////////////////////////////
TGUIHandle *C3DLibInterface::createLabel(TGUIHandle *handle, int x, int y, int c, char *t)
{
  if (!checkBinding())
    return NULL;

  return pLibRef->screen2D.createLabel(handle, x, y, c, t);
}